home *** CD-ROM | disk | FTP | other *** search
/ Nebula 1 / Nebula One.iso / Communications / pcomm / Source / main.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-06-12  |  7.8 KB  |  368 lines

  1. /*
  2.  * Pcomm is a public domain telecommunication program for Unix that
  3.  * is designed to operate similar to the MSDOS program, ProComm.
  4.  * ProComm (TM) is copyrighted by Datastorm Technologies, Inc.
  5.  *
  6.  * Emmet P. Gray            US Army, HQ III Corps & Fort Hood
  7.  * ...!uunet!uiucuxc!fthood!egray    Attn: AFZF-DE-ENV
  8.  *                    Directorate of Engineering & Housing
  9.  *                    Environmental Management Office
  10.  *                    Fort Hood, TX 76544-5057
  11.  *
  12.  *    Release v1.0    12 Mar 88
  13.  *    Release v1.1    21 Aug 88
  14.  *    Release v1.2.0     4 Feb 89
  15.  *    Patch #1    18 Feb 89
  16.  *    Patch #2    11 Mar 89
  17.  *    Patch #3    11 May 89
  18.  *    Patch #4    23 Jun 89
  19.  *    Patch #5    30 Oct 89
  20.  *    Patch #6     8 Nov 89
  21.  *    Patch #7    13 Jan 90
  22.  *    Patch #8    20 Jan 90
  23.  *    Patch #9     1 Sep 90
  24.  *    Patch #10    30 Dec 90
  25.  */
  26.  
  27. #include <stdio.h>
  28. #include <ctype.h>
  29. #include <signal.h>
  30. #include <curses.h>
  31. #include <sys/types.h>
  32. #include <sys/stat.h>
  33. #define    MAIN
  34. #include "config.h"
  35. #include "dial_dir.h"
  36. #include "extrnl.h"
  37. #include "misc.h"
  38. #include "modem.h"
  39. #include "param.h"
  40. #include "status.h"
  41.  
  42. #ifndef OLDCURSES
  43. #include <term.h>
  44. #else /* OLDCURSES */
  45. #ifdef UNIXPC
  46. #include <sgtty.h>
  47. #endif /* UNIXPC */
  48. char tcbuf[1024];
  49. struct sgttyb t_mode, c_mode;
  50. #ifndef cbreak
  51. #define cbreak crmode
  52. #endif
  53. #endif /* OLDCURSES */
  54.  
  55. #ifdef SHAREDMEM
  56. int shm_id;
  57. #endif /* SHAREDMEM */
  58.  
  59. struct DIAL_DIR *dir;
  60. struct EXTRNL *extrnl;
  61. struct MODEM *modem;
  62. struct PARAM *param;
  63. struct STATUS *status;
  64.  
  65. int fd = -1;                /* file descriptor for port */
  66. int xmc;                /* magic cookie terminal */
  67. int msg_status;                /* read/write permissions on TTY */
  68. char *null_ptr = "";            /* generic null pointer */
  69.  
  70. main(argc, argv)
  71. int argc;
  72. char *argv[];
  73. {
  74.     extern char *optarg;
  75.     int c, i, code;
  76.     static int quit(), match_ci();
  77.     char *mytty, *ttyname(), *term, *getenv(), *sys_name, *str_dup();
  78.     char *extra_dir, buf[80], message[80];
  79.     struct DIAL_DIR *read_dir();
  80.     struct EXTRNL *read_extrnl();
  81.     struct MODEM *read_modem();
  82.     struct PARAM *read_param();
  83.     struct STATUS *init();
  84.     struct stat stbuf;
  85.     void exit(), error_win(), free_ptr();
  86. #ifdef OLDCURSES
  87.     char *tgetstr(), *t, tb[1024];
  88.     t = tcbuf;
  89. #endif /* OLDCURSES */
  90.  
  91.     signal(SIGINT, SIG_IGN);
  92.     signal(SIGQUIT, SIG_IGN);
  93.     signal(SIGTERM, (SIG_TYPE(*) ()) quit);
  94.     signal(SIGHUP, (SIG_TYPE(*) ()) quit);
  95.  
  96.     sys_name = NULL;
  97.     extra_dir = NULL;
  98.                     /* the command line */
  99.     while ((c = getopt(argc, argv, "d:f:")) != EOF) {
  100.         switch (c) {
  101.             case 'd':    /* the extra directory to search */
  102.                 extra_dir = str_dup(optarg);
  103.                 break;
  104.             case 'f':    /* the short cut into the dialing dir */
  105.                 sys_name = str_dup(optarg);
  106.                 break;
  107.             case '?':    /* default */
  108.                 fprintf(stderr, "Usage: pcomm [-d directory] [-f system name]\n");
  109.                 exit(1);
  110.                 break;
  111.         }
  112.     }
  113.                     /* get terminal type */
  114.     term = getenv("TERM");
  115.     if (term == NULL || *term == '\0') {
  116.         fprintf(stderr, "Windows not supported (TERM not defined)\n");
  117.         exit(1);
  118.     }
  119.                     /* see if terminfo entry exists */
  120. #ifdef OLDCURSES
  121.     i = tgetent(tb, term);
  122. #else /* OLDCURSES */
  123.     setupterm(term, 1, &i);
  124. #endif /* OLDCURSES */
  125.  
  126.     if (i != 1) {
  127.         fprintf(stderr, "Windows not supported (no terminfo data for \"%s\")\n", term);
  128.         exit(1);
  129.     }
  130.                     /* minimum screen size */
  131. #ifdef OLDCURSES
  132.     if (tgetnum("co") < 80 || tgetnum("li") < 24) {
  133. #else /* OLDCURSES */
  134.     if (columns < 80 || lines < 24) {
  135. #endif /* OLDCURSES */
  136.         fprintf(stderr, "Windows not supported (minimum 80x24 screen required)\n");
  137.         exit(1);
  138.     }
  139.                     /* must have cursor movement */
  140. #ifdef OLDCURSES
  141.     if (tgetstr("cm", &t) == NULL) {
  142. #else /* OLDCURSES */
  143.     if (cursor_address == NULL) {
  144. #endif /* OLDCURSES */
  145.         fprintf(stderr, "Windows not supported (terminal too dumb)\n");
  146.         exit(1);
  147.     }
  148.                     /* load magic cookie variable */
  149. #ifdef OLDCURSES
  150.     xmc = tgetnum("sg");
  151. #else /* OLDCURSES */
  152.     xmc = magic_cookie_glitch;
  153. #endif /* OLDCURSES */
  154.                     /* ok... now let's go! */
  155. #ifdef OLDCURSES
  156.     ioctl(0, TIOCGETP, &t_mode);
  157. #endif /* OLDCURSES */
  158.  
  159.     initscr();
  160.     nonl();
  161.     cbreak();
  162.     noecho();
  163. #ifdef XENIX_3
  164.     raw();
  165. #endif /* XENIX_3 */
  166.  
  167. #ifdef OLDCURSES
  168.     ioctl(0, TIOCGETP, &c_mode);
  169. #endif /* OLDCURSES */
  170.  
  171.     dir = (struct DIAL_DIR *) NULL;
  172.     extrnl = (struct EXTRNL *) NULL;
  173.     param = (struct PARAM *) NULL;
  174.     modem = (struct MODEM *) NULL;
  175.                     /* show the herald, return status */
  176.     status = init(sys_name);
  177.                     /* get "msgs" status */
  178.     if (mytty = ttyname(0)) {
  179.         stat(mytty, &stbuf);
  180.         msg_status = stbuf.st_mode & 0777;
  181.         chmod(mytty, 0600);
  182.     }
  183.  
  184.     mvaddstr(12, 31, "Initializing...");
  185.     refresh();
  186.                     /* read the support files */
  187.     param = read_param(extra_dir);
  188.     dir = read_dir(extra_dir);
  189.     extrnl = read_extrnl(extra_dir);
  190.     modem = read_modem(extra_dir);
  191.  
  192.                     /* warning about screen size */
  193.     if (LINES > MAX_ROW || COLS > MAX_COL-1)
  194.         error_win(0, "Your screen size exceeds an internal Pcomm limit",
  195.          "The edges of the screen may contain garbage");
  196.  
  197.                     /* short-cut to dialing window? */
  198.     code = 0;
  199.     if (sys_name != NULL) {
  200.         for (i=1; i<dir->d_entries+1; i++) {
  201.             if (match_ci(dir->name[i], sys_name)) {
  202.                 dir->q_num[0] = i;
  203.                 dir->d_cur = i;
  204.                 break;
  205.             }
  206.         }
  207.                     /* if match is found */
  208.         if (dir->q_num[0] != -1)
  209.             code = dial_win();
  210.         else {
  211.             sprintf(buf, "Can't match \"%s\" in dialing directory", sys_name);
  212.             sprintf(message, "file \"%s\"", dir->d_path);
  213.             error_win(0, buf, message);
  214.         }
  215.         free_ptr(sys_name);
  216.     }
  217.                     /* start terminal dialogue */
  218.     terminal(extra_dir, code);
  219.     exit(0);
  220. }
  221.  
  222. /*
  223.  * Something dreadful happened...  Clean up the mess we made with the
  224.  * TTY driver and release the phone line.
  225.  */
  226.  
  227. static int
  228. quit()
  229. {
  230.     void cleanup();
  231.  
  232.     cleanup(1);
  233.                     /* never returns... */
  234.     return(0);
  235. }
  236.  
  237. /*
  238.  * Check write permission with the real UID and GID.  Returns a 0 on
  239.  * permission denied, 1 on OK, and 2 on OK-but the file already exists.
  240.  */
  241.  
  242. int
  243. can_write(file)
  244. char *file;
  245. {
  246.     char *p, path[256], *strcpy(), *strrchr();
  247.  
  248.     strcpy(path, file);
  249.                     /* dissect the path component */
  250.     if (p = strrchr(path, '/'))
  251.         *p = '\0';
  252.     else
  253.         strcpy(path, ".");
  254.                     /* if it already exists */
  255.     if (!access(file, 0)) {
  256.         if (!access(file, 2))
  257.             return(OK_BUT_EXISTS);
  258.         return(DENIED);
  259.     }
  260.                     /* if path is writable */
  261.     if (!access(path, 2))
  262.         return(WRITE_OK);
  263.     return(DENIED);
  264. }
  265.  
  266. /*
  267.  * Check the read and write permissions before opening a file.  This
  268.  * is a horrible kludge to work around the fact that a lot of systems
  269.  * that claim to be SVID compatible don't treat setuid(2) and setgid(2)
  270.  * properly.  For example, on a Masscomp, you can't flip-flop back and
  271.  * forth between the real and effective UID/GID.
  272.  */
  273.  
  274. FILE *
  275. my_fopen(file, mode)
  276. char *file, *mode;
  277. {
  278.     FILE *fp;
  279.  
  280. #ifdef SETUGID
  281. #ifdef SETUID_BROKE
  282.     switch (*mode) {
  283.         case 'a':
  284.         case 'w':
  285.             switch(can_write(file)) {
  286.                 case DENIED:
  287.                     fp = (FILE *) NULL;
  288.                     break;
  289.                 case OK_BUT_EXISTS:
  290.                     fp = fopen(file, mode);
  291.                     break;
  292.                 case WRITE_OK:
  293.                     fp = fopen(file, mode);
  294.                     chown(file, getuid(), getgid());
  295.                     break;
  296.             }
  297.             break;
  298.         case 'r':
  299.             if (access(file, 4))
  300.                 fp = (FILE *) NULL;
  301.             else
  302.                 fp = fopen(file, mode);
  303.             break;
  304.     }
  305. #else /* SETUID_BROKE */
  306.     int euid, egid;
  307.  
  308.     euid = geteuid();
  309.     egid = getegid();
  310.                     /* abdicate the throne */
  311.     setuid(getuid());
  312.     setgid(getgid());
  313.  
  314.     fp = fopen(file, mode);
  315.                     /* put things back */
  316.     setuid(euid);
  317.     setgid(egid);
  318. #endif /* SETUID_BROKE */
  319.     return(fp);
  320. #else /* SETUGID */
  321.     return(fopen(file, mode));
  322. #endif /* SETUGID */
  323. }
  324.  
  325. /*
  326.  * See if s2 in contained in s1 (case insensitive).  Returns a 1 on yes,
  327.  * and a 0 on no.
  328.  */
  329.  
  330. static int
  331. match_ci(s1, s2)
  332. char *s1, *s2;
  333. {
  334.     int i;
  335.     char str1[128], str2[128], *strstr();
  336.  
  337.                     /* copy the strings to lower case */
  338.     i = 0;
  339.     while(*s1) {
  340.         if (isupper(*s1))
  341.             str1[i++] = tolower(*s1);
  342.         else
  343.             str1[i++] = *s1;
  344.  
  345.         if (i >= 127)
  346.             break;
  347.         s1++;
  348.     }
  349.     str1[i] = '\0';
  350.  
  351.     i = 0;
  352.     while(*s2) {
  353.         if (isupper(*s2))
  354.             str2[i++] = tolower(*s2);
  355.         else
  356.             str2[i++] = *s2;
  357.  
  358.         if (i >= 127)
  359.             break;
  360.         s2++;
  361.     }
  362.     str2[i] = '\0';
  363.                     /* do they match? */
  364.     if (strstr(str1, str2))
  365.         return(1);
  366.     return(0);
  367. }
  368.